<?php
declare(strict_types=1);

namespace App\Logic\User\Service\User;

use App\Constant\CacheKey;
use App\Exceptions\DbException;
use App\Library\AppFunction;
use App\Library\RedisClient;
use App\Library\SnowFlakeId;
use App\Logic\User\Repository\Image\ImageCollectionRepository;
use App\Logic\User\Repository\Image\ImageRepository;
use App\Logic\User\Repository\Image\ImageShareRepository;
use App\Logic\User\Repository\User\AuthorFansRepository;
use App\Logic\User\Repository\User\AuthorRepository;
use App\Logic\User\Service\BaseService;
use App\Logic\User\Service\UserServiceInterface;
use App\Models\User\Image\ImageCollection;
use App\Models\User\Image\ImageDownload;
use App\Models\User\Image\ImageShare;
use App\Models\User\User\AuthorFans;
use Closure;

class AuthorService extends BaseService implements UserServiceInterface
{

    public static function searchWhere(array $requestParams): Closure
    {
        return function ($query) use ($requestParams) {
            extract($requestParams);
            if (!empty($user_uid)) {
                $query->where("user_uid", "=", $requestParams["user_uid"]);
            }
            if (!empty($uid)) {
                $query->where("uid", "=", $requestParams["uid"]);
            }
        };
    }

    public function serviceSelect(array $requestParams): array
    {
        return [];
    }

    public function serviceCreate(array $requestParams): array
    {
        return [];
    }

    /**
     * 创作者粉丝列表
     * @param array $requestParams
     * @return array
     * @throws DbException
     */
    public function serviceFansList(array $requestParams): array
    {
        $authorUid = $this->authorUserUid();
        $authorFansRepository = new AuthorFansRepository();
        return $authorFansRepository->repositoryAuthorSelect(function ($query) use ($authorUid) {
            $query->where("author_uid", "=", $authorUid);
        }, (int)($requestParams["size"] ?? 20), ["uid", "user_uid", "author_uid", "created_at as attention_time"]);
    }

    /**
     * 查询作者数据中心的收藏
     * @param array $requestParams
     * @return array
     * @throws DbException
     */
    public function serviceCollection(array $requestParams): array
    {
        $authorUid = $this->authorUserUid();
        $imageCollectionRepository = new ImageCollectionRepository();
        return $imageCollectionRepository->repositoryAuthorSelect(function ($query) use ($authorUid) {
            $query->where("author_uid", "=", $authorUid);
        }, (int)($requestParams["size"] ?? 20), ["uid", "user_uid", "image_uid", "created_at as attention_time"]);
    }

    /**
     * 查询作者数据中心分享
     * @param array $requestParams
     * @return array
     * @throws DbException
     */
    public function serviceShare(array $requestParams): array
    {
        $authorUid = $this->authorUserUid();
        $imageShareRepository = new ImageShareRepository();
        return $imageShareRepository->repositoryAuthorSelect(function ($query) use ($authorUid) {
            $query->where("author_uid", "=", $authorUid);
        }, (int)($requestParams["size"] ?? 20), ["uid", "user_uid", "image_uid", "created_at as attention_time"]);
    }

    public function serviceUpdate(array $requestParams): array
    {
        $requestParams["user_uid"] = $this->getUserUid();
        $authorRepository = new AuthorRepository();
        $authorInfo = $authorRepository->repositoryFind(self::searchWhere($requestParams), ["uid", "is_forbidden", "profession"]);
        if (!empty($authorInfo) && $authorInfo["is_forbidden"] == 1) {
            return ["code" => 1, "msg" => "账号已被禁用"];
        }
        if (!empty($authorInfo)) {
            $updateRow = $authorRepository->repositoryUpdate([
                ["user_uid", "=", $requestParams["user_uid"]]
            ], [
                "nickname"      => $requestParams["nickname"],
                "qr_url"        => $requestParams["qr_url"],
                "remark"        => $requestParams["remark"],
                "birthday"      => $requestParams["birthday"],
                "gender"        => $requestParams["gender"],
                "profession"    => $requestParams["profession"],
                "audit_status"  => 1,
                "constellation" => AppFunction::getConstellation($requestParams["birthday"]),
            ]);
            if ($updateRow) {
                return ["code" => 2, "msg" => "更新成功 等待审核"];
            }
            return ["code" => 3, "msg" => "更新失败 请重试"];
        }
        $createResult = $authorRepository->repositoryCreate([
            "uid"           => SnowFlakeId::getId(),
            "user_uid"      => $requestParams["user_uid"],
            "nickname"      => $requestParams["nickname"],
            "qr_url"        => $requestParams["qr_url"],
            "remark"        => $requestParams["remark"],
            "birthday"      => $requestParams["birthday"],
            "gender"        => $requestParams["gender"],
            "profession"    => $requestParams["profession"],
            "audit_status"  => 1,
            "constellation" => AppFunction::getConstellation($requestParams["birthday"]),
        ]);
        if ($createResult) {
            return ["code" => 4, "msg" => "请等待审核"];
        }
        return ["code" => 5, "msg" => "提交失败 请重试"];
    }

    public function serviceDelete(array $requestParams): int
    {
        return 0;
    }

    public function serviceFind(array $requestParams): array
    {
        $requestParams["user_uid"] = $this->getUserUid();
        $authorInfo = (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams), [
            "uid", "user_uid", "nickname", "is_forbidden", "series_count", "qr_url", "remark",
            "birthday", "gender", "profession", "nickname", "constellation"
        ]);
        if (!empty($authorInfo)) {
            if ($authorInfo["is_forbidden"] != 1) {
                return [
                    "code"       => 3,
                    "nickname"   => $authorInfo["nickname"],
                    "qr_url"     => $authorInfo["qr_url"],
                    "remark"     => $authorInfo["remark"],
                    "birthday"   => $authorInfo["birthday"],
                    "gender"     => $authorInfo["gender"],
                    "profession" => $authorInfo["profession"],
                ];
            }
            return ["code" => 1, "msg" => "权限被禁用"];
        }
        return ["code" => 0, "msg" => "信息不存在"];
    }

    public function getAuthorInfo(array $requestParams): array
    {
        return (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams), ["nickname", "qr_url", "remark", "uid"]);
    }

    /**
     * 发布壁纸作品
     * @param array $requestParams
     * @return array
     */
    public function servicePublish(array $requestParams): array
    {
        $userId = $this->getUserUid();
        $requestParams["user_uid"] = $userId;
        $authorInfo = (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams), ["uid", "is_forbidden", "audit_status"]);
        if (count($authorInfo) == 0) {
            return ["code" => 1, "msg" => "请先认证为作者"];
        }
        if ($authorInfo["is_forbidden"] == 1) {
            return ["code" => 1, "msg" => "发布权限已被禁用"];
        }
        if ($authorInfo["audit_status"] == 3) {
            return ["code" => 1, "msg" => "认证审核中"];
        }
        if ($authorInfo["audit_status"] == 2) {
            return ["code" => 1, "msg" => "认证被驳回 请重新认证"];
        }
        $authorId = $authorInfo["uid"];
        $imageArray = json_decode($requestParams["image_list"], true);
        $imageList = [];
        $imageUid = SnowFlakeId::getId();
        foreach ($imageArray as $value) {
            $pathInfo = pathinfo($value);
            $imageList[] = [
                "uid"        => SnowFlakeId::getId(),
                "user_uid"   => $userId,
                "author_uid" => $authorId,
                "image_uid"  => $imageUid,
                "url"        => $pathInfo["dirname"] . "/",
                "path"       => $pathInfo["basename"],
                "download"   => 0,
                "title"      => $requestParams["image_title"],
                "collect"    => 0,
                "created_at" => date("Y-m-d H:i:s"),
                "updated_at" => date("Y-m-d H:i:s"),
            ];
        }
        $image = [
            "uid"          => $imageUid,
            "user_uid"     => $userId,
            "author_uid"   => $authorId,
            "series_uid"   => $requestParams["image_series_uid"],
            "category_uid" => $requestParams["image_category_uid"],
            "item_count"   => count($imageArray),
            "url"          => $imageList[0]["url"],
            "path"         => $imageList[0]["path"],
            "title"        => $requestParams["image_title"],
            "download"     => 0,
            "collect"      => 0,
            "is_show"      => 2,
            "device_type"  => $requestParams["image_device"]
        ];
        if ((new ImageRepository())->repositoryCreate(["image" => $image, "image_item" => $imageList])) {
            return ["code" => 0, "msg" => "请等待审核"];
        }
        return ["code" => 1, "msg" => "发布失败"];
    }

    public function serviceTotalData(): array
    {
        $requestParams["user_uid"] = $this->getUserUid();
        $identInfo = (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams),
            ["audit_msg", "audit_status", "audit_at", "is_forbidden", "uid"]);
        if (!empty(RedisClient::client()->exists(CacheKey::AuthorTotal . $identInfo["uid"]))) {
            return RedisClient::client()->hMGet(CacheKey::AuthorTotal . $identInfo["uid"], ["fans", "collection", "download", "share"]);
        }
        $totalData = [
            "fans"       => 0,// 粉丝总数
            "collection" => 0,// 收藏总数
            "download"   => 0,// 下载总数
            "share"      => 0// 分享总数
        ];
        if (!empty($identInfo) && $identInfo["audit_status"] == 1) {
            $totalData["download"] = ImageDownload::query()->where("author_uid", "=", $identInfo["uid"])->count();
            $totalData["fans"] = AuthorFans::query()->where("author_uid", "=", $identInfo["uid"])->count();
            $totalData["collection"] = ImageCollection::query()->where("author_uid", "=", $identInfo["uid"])->count();
            $totalData["share"] = ImageShare::query()->where("author_uid", "=", $identInfo["uid"])->count();
        }
        RedisClient::client()->hMSet(CacheKey::AuthorTotal . $identInfo["uid"], $totalData);
        RedisClient::client()->expire(CacheKey::AuthorTotal . $identInfo["uid"], 7200);
        return $totalData;
    }

    public function serviceCurrentWeek(): array
    {
        $requestParams["user_uid"] = $this->getUserUid();
        $identInfo = (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams),
            ["audit_msg", "audit_status", "audit_at", "is_forbidden", "uid"]);
        if (!empty(RedisClient::client()->exists(CacheKey::AuthorCurrentWeek . $identInfo["uid"]))) {
            return RedisClient::client()->hMGet(CacheKey::AuthorCurrentWeek . $identInfo["uid"], ["fans", "collection", "download", "share"]);
        }
        $totalData = [
            "fans"       => 0,// 粉丝总数
            "collection" => 0,// 收藏总数
            "download"   => 0,// 下载总数
            "share"      => 0// 分享总数
        ];
        if (!empty($identInfo) && $identInfo["audit_status"] == 1) {
            $totalData["download"] = ImageDownload::query()
                ->where("author_uid", "=", $identInfo["uid"])
                ->whereBetween("created_at", AppFunction::getWeekFirstLastDay())
                ->count();

            $totalData["fans"] = AuthorFans::query()
                ->where("author_uid", "=", $identInfo["uid"])
                ->whereBetween("created_at", AppFunction::getWeekFirstLastDay())
                ->count();

            $totalData["collection"] = ImageCollection::query()
                ->where("author_uid", "=", $identInfo["uid"])
                ->whereBetween("created_at", AppFunction::getWeekFirstLastDay())
                ->count();

            $totalData["share"] = ImageShare::query()
                ->where("author_uid", "=", $identInfo["uid"])
                ->whereBetween("created_at", AppFunction::getWeekFirstLastDay())
                ->count();
        }
        RedisClient::client()->hMSet(CacheKey::AuthorCurrentWeek . $identInfo["uid"], $totalData);
        RedisClient::client()->expire(CacheKey::AuthorCurrentWeek . $identInfo["uid"], 7200);
        return $totalData;
    }

    public function serviceAuditState(): array
    {
        $requestParams["user_uid"] = $this->getUserUid();
        $identInfo = (new AuthorRepository())->repositoryFind(self::searchWhere($requestParams),
            ["audit_msg", "audit_status", "audit_at", "is_forbidden"]);
        if (count($identInfo)) {
            return ["code" => 1, "info" => $identInfo];
        }
        return ["code" => 0, "info" => [],];
    }
}
